using System;
using System.IO;
using Microsoft.CRM.ThirdParty.Extensions.ProjectCreator.Eventing;

namespace Microsoft.CRM.ThirdParty.Extensions.ProjectCreator.Domain
{
    public class ProjectCreator
    {
        private readonly ProjectEventAggregator _aggregator;

        public ProjectCreator(ProjectEventAggregator aggregator)
        {
            _aggregator = aggregator;
        }

        public void CreatorProject(string name, string location)
        {
            CreateProjectFolder(name, location);
            CreateLibraries(name, location);
            CreateTools(name, location);
            CreateSolutionFile(name, location);
            UpdateSolutionFile(name, location);
            CreateProjectDirectoriesAndProjFiles(name, location);
            CreateBuildScripts(name, location);
        }

        private void CreateBuildScripts(string name, string location)
        {
            _aggregator.NotifyChange("Creating Build Files");
            var root = Path.Combine(location, name);

            var pluginsxmlfile = Path.Combine(root, "Plugins.xml");
            var cipluginsbuildfile = Path.Combine(root, "ci-plugins-build.build");
            var cipluginsbuildreleasebatfile = Path.Combine(root, "ci-plugins-release-build.bat");
            var cipluginsbuilddebugbatfile = Path.Combine(root, "ci-plugins-debug-build.bat");

            File.Copy("Plugins.xml", pluginsxmlfile);
            File.Copy("ci-plugins-release-build.bat", cipluginsbuildreleasebatfile);
            File.Copy("ci-plugins-debug-build.bat", cipluginsbuilddebugbatfile);
            File.Copy("ci-plugins-build.build", cipluginsbuildfile);

            string cipluginsbuildfilecontents = File.ReadAllText(cipluginsbuildfile);
            cipluginsbuildfilecontents = cipluginsbuildfilecontents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(cipluginsbuildfile, cipluginsbuildfilecontents);

            string pluginsxmlfilecontents = File.ReadAllText(pluginsxmlfile);
            pluginsxmlfilecontents = pluginsxmlfilecontents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(pluginsxmlfile, pluginsxmlfilecontents);

        }

        private void CreateProjectDirectoriesAndProjFiles(string name, string location)
        {
            _aggregator.NotifyChange("Creating Project Files");
            var root = Path.Combine(location, name);
            var src = Path.Combine(root, "src");
            var solution = Path.Combine(src, name);
            var wf = Path.Combine(solution, name + ".WorkflowActivities");
            var plugins = Path.Combine(solution, name + ".Plugins");
            var pulugins = Path.Combine(solution, name + ".Plugins.UnitTests");
            var dl = Path.Combine(solution, name + ".DataImport");
            var dlu = Path.Combine(solution, name + ".DataImport.UnitTests");

            Directory.CreateDirectory(wf);
            Directory.CreateDirectory(plugins);
            Directory.CreateDirectory(pulugins);
            Directory.CreateDirectory(dl);
            Directory.CreateDirectory(dlu);

            var pfile = Path.Combine(plugins, name + ".Plugins.csproj");
            var wfile = Path.Combine(wf, name + ".WorkflowActivities.csproj");
            var pufile = Path.Combine(pulugins, name + ".Plugins.UnitTests.csproj");
            var dlfile = Path.Combine(dl, name + ".DataImport.csproj");
            var dlufile = Path.Combine(dlu, name + ".DataImport.UnitTests.csproj");

            File.Copy("Plugins.csproj", pfile);
            File.Copy("WorkflowActivities.csproj", wfile);
            File.Copy("Plugins.UnitTests.csproj", pufile);
            File.Copy("DataImport.csproj", dlfile);
            File.Copy("DataImport.UnitTests.csproj", dlufile);

            string pcontents = File.ReadAllText(pfile);
            pcontents = pcontents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(pfile, pcontents);

            string pucontents = File.ReadAllText(pufile);
            pucontents = pucontents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(pufile, pucontents);

            string wcontents = File.ReadAllText(wfile);
            wcontents = wcontents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(wfile, wcontents);

            var ofile = Path.Combine(plugins, "OpportunityPreCreatePlugin.cs");

            _aggregator.NotifyChange("Copying Sample Opportunity Pre Create Plugin");
            File.Copy("OpportunityPreCreatePlugin.cs",ofile );

            string ocontents = File.ReadAllText(ofile);
            ocontents = ocontents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(ofile, ocontents);

            var sufile = Path.Combine(pulugins, "SampleTest.cs");

            _aggregator.NotifyChange("Copying Sample Unit Test");
            File.Copy("SampleTest.cs", sufile);

            string sucontents = File.ReadAllText(sufile);
            sucontents = sucontents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(sufile, sucontents);

            _aggregator.NotifyChange("Copying Plugin Snk File");
            File.Copy("PluginsKey.snk", Path.Combine(plugins, "PluginsKey.snk"));
            File.Copy("PluginsKey.snk", Path.Combine(wf, "PluginsKey.snk"));

        }

        private void CreateLibraries(string name, string location)
        {
            _aggregator.NotifyChange("Copying CRM Libraries");
            var root = Path.Combine(location, name);
            CopyFolder("LibsToCopy", Path.Combine(root, "libs"));
        }

        private void CreateTools(string name, string location)
        {
            _aggregator.NotifyChange("Copying CRM Tools Folder");
            var root = Path.Combine(location, name);
            CopyFolder("ToolsToCopy", Path.Combine(root, "tools"));
        }

        private void CreateSolutionFile(string name, string location)
        {
            _aggregator.NotifyChange("Creating Solution File");
            var root = Path.Combine(location, name);
            var src = Path.Combine(root, "src");
            var solution = Path.Combine(src, name);
            File.Copy("Solution.sln", Path.Combine(solution, name + ".sln"));
        }

        private void UpdateSolutionFile(string name, string location)
        {
            _aggregator.NotifyChange("Updating Solution File");
            var root = Path.Combine(location, name);
            var src = Path.Combine(root, "src");
            var solution = Path.Combine(src, name);
            var file = Path.Combine(solution, name + ".sln");
            string contents = File.ReadAllText(file);
            contents = contents.Replace("[ProjectNameHere]", name);
            File.WriteAllText(file, contents);
        }

        private void CreateProjectFolder(string name, string location)
        {
            _aggregator.NotifyChange(String.Format("Creating project {0} at {1}", name, location));
            var root = Path.Combine(location, name);
            Directory.CreateDirectory(root);
            var src = Path.Combine(root, "src");
            _aggregator.NotifyChange(String.Format("Creating Source Folder at {0}", src));
            Directory.CreateDirectory(src);
            var solution = Path.Combine(src, name);
            _aggregator.NotifyChange(String.Format("Creating Solution Folder at {0}", solution));
            Directory.CreateDirectory(solution);
        }

        private void CopyFolder(string sourceFolder, string destFolder)
        {
            if (!Directory.Exists(destFolder))
                Directory.CreateDirectory(destFolder);
            string[] files = Directory.GetFiles(sourceFolder);
            foreach (string file in files)
            {
                string name = Path.GetFileName(file);
                string dest = Path.Combine(destFolder, name);
                File.Copy(file, dest);
            }
            string[] folders = Directory.GetDirectories(sourceFolder);
            foreach (string folder in folders)
            {
                string name = Path.GetFileName(folder);
                string dest = Path.Combine(destFolder, name);
                CopyFolder(folder, dest);
            }
        }
    }
}